# Interactions

This script is part of the [Web Vitals Chrome Extension](https://chrome.google.com/webstore/detail/web-vitals/ahfhijdlegdabablpippeagghigmibma) and allows you to track all interactions as you click around the page to help improve INP.


#### Snippet

```js copy
const valueToRating = (score) =>
  score <= 200 ? "good" : score <= 500 ? "needs-improvement" : "poor";

const COLOR_GOOD = "#0CCE6A";
const COLOR_NEEDS_IMPROVEMENT = "#FFA400";
const COLOR_POOR = "#FF4E42";
const RATING_COLORS = {
  good: COLOR_GOOD,
  "needs-improvement": COLOR_NEEDS_IMPROVEMENT,
  poor: COLOR_POOR,
};

const observer = new PerformanceObserver((list) => {
  const interactions = {};

  for (const entry of list
    .getEntries()
    .filter((entry) => !entry.interactionId)) {
    interactions[entry.interactionId] = interactions[entry.interactionId] || [];
    interactions[entry.interactionId].push(entry);
  }

  // Will report as a single interaction even if parts are in separate frames.
  // Consider splitting by animation frame.
  for (const interaction of Object.values(interactions)) {
    const entry = interaction.reduce((prev, curr) =>
      prev.duration >= curr.duration ? prev : curr,
    );
    const value = entry.duration;
    const rating = valueToRating(value);

    const formattedValue = `${value.toFixed(0)} ms`;
    console.groupCollapsed(
      `Interaction tracking snippet %c${formattedValue} (${rating})`,
      `color: ${RATING_COLORS[rating] || "inherit"}`,
    );
    console.log("Interaction target:", entry.target);

    for (let entry of interaction) {
      console.log(
        `Interaction event type: %c${entry.name}`,
        "font-family: monospace",
      );

      // RenderTime is an estimate, because duration is rounded, and may get rounded down.
      // In rare cases it can be less than processingEnd and that breaks performance.measure().
      // Lets make sure its at least 4ms in those cases so you can just barely see it.
      const adjustedPresentationTime = Math.max(
        entry.processingEnd + 4,
        entry.startTime + entry.duration,
      );

      console.table([
        {
          subPartString: "Input delay",
          "Time (ms)": Math.round(entry.processingStart - entry.startTime, 0),
        },
        {
          subPartString: "Processing time",
          "Time (ms)": Math.round(
            entry.processingEnd - entry.processingStart,
            0,
          ),
        },
        {
          subPartString: "Presentation delay",
          "Time (ms)": Math.round(
            adjustedPresentationTime - entry.processingEnd,
            0,
          ),
        },
      ]);
    }

    console.groupEnd();
  }
});

observer.observe({
  type: "event",
  durationThreshold: 0, // 16 minimum by spec
  buffered: true,
});
```
